package com.chen.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.constant.ResultConstant;
import com.chen.context.BaseContext;
import com.chen.exception.BaseException;
import com.chen.exception.NotFoundUserError;
import com.chen.exception.NotLoginError;
import com.chen.mapper.ContactPersonMapper;
import com.chen.mapper.UsersMapper;
import com.chen.pojo.dto.ContactPersonDto;
import com.chen.pojo.dto.GroupPersonIdDto;
import com.chen.pojo.dto.PersonGroupDto;
import com.chen.pojo.entity.ContactGroup;
import com.chen.pojo.entity.ContactMethods;
import com.chen.pojo.entity.ContactPerson;
import com.chen.pojo.entity.User;
import com.chen.pojo.vo.ContactGroupVo;
import com.chen.pojo.vo.ContactMethodsVo;
import com.chen.pojo.vo.ContactPersonVo;
import com.chen.service.ContactGroupService;
import com.chen.service.ContactMethodsService;
import com.chen.service.ContactPersonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 陈子安
 * @since 2023-11-30
 */
@Service
@Slf4j
public class ContactPersonServiceImpl extends ServiceImpl<ContactPersonMapper, ContactPerson> implements ContactPersonService {

    @Autowired
    private ContactPersonMapper contactPersonMapper;

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private ContactMethodsService contactMethodsService;

    @Autowired
    private ContactGroupService contactGroupService;


    @Override
    /*
     * 思路：
     *
     *       2。 根据联系人 id 查询中间表得到中间表信息
     *       3.  根据联系人 id 查询联系方式
     *       4.  对上上的数据经封装成一个 vo 对象
     *
     * */
    public List<ContactPersonVo> getContactsAll() {

        Long currentId = BaseContext.getCurrentId();
        User user = usersMapper.selectById(currentId);
        // 如果是管理员，直接查询所有联系人
        List<ContactPerson> personList = new ArrayList<>();
        if (user.getIsAdmin() == 1) {
            personList = list();
        } else if (user.getIsAdmin() == 0) {
            // 如果是普通用户，根据用户id查询联系人
            LambdaUpdateWrapper<ContactPerson> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(ContactPerson::getUserId, currentId);
            personList = list(wrapper);
        }

        if (personList == null || personList.size() == 0) {
            return null;
        }
        // 先将用户的基础信息放进vo中先
        List<ContactPersonVo> vo = BeanUtil.copyToList(personList, ContactPersonVo.class);

        //1. 根据查询出所有联系人id
        List<Integer> ids = personList.stream().map(ContactPerson::getId).collect(Collectors.toList());

        // 根据联系人id查询联系人对应的组信息 这里封装这里 联系人id 、 组id、 组名、组描述
        List<GroupPersonIdDto> gpDto = contactGroupService.getContactGroupByPersonId(ids);

        Map<Integer, List<ContactGroupVo>> gpMap = new HashMap<>();
        for (GroupPersonIdDto groupPersonIdDto : gpDto) {
            gpMap.put(groupPersonIdDto.getPersonId(), BeanUtil.copyToList(groupPersonIdDto.getContactGroupVos(), ContactGroupVo.class));
        }

        // 根据联系人id查询联系方式  这里封装了 联系人id 、 联系方式id、 联系方式名称、 联系方式描述
        List<ContactMethods> contactMethodsByPersonId = contactMethodsService.getContactMethodsByPersonId(ids);

        // 联系人id和联系方式信息
        Map<Integer, List<ContactMethods>> methodsMap = contactMethodsByPersonId.stream().collect(Collectors.groupingBy(ContactMethods::getPersonId));

        Map<Integer, List<ContactMethodsVo>> methodsMapVo = new HashMap<>();

        methodsMap.forEach((x, y) -> {
            methodsMapVo.put(x, BeanUtil.copyToList(y, ContactMethodsVo.class));
        });

        for (int i = 0; i < vo.size(); i++) {
            ContactPersonVo contactPersonVo = vo.get(i);
            if (i < gpMap.size()) {
                contactPersonVo.setGroups(gpMap.get(contactPersonVo.getId()));
            }
            // 封装组新
            if (i < methodsMapVo.size()) {
                contactPersonVo.setContactMethods(methodsMapVo.get(contactPersonVo.getId()));
            }
        }
        return vo;

    }


    @Override
    public ContactPersonVo getContactByContactId2(Integer contactId) {
        Long currentId = BaseContext.getCurrentId();

        ContactPerson byId = getById(contactId);
        if (byId == null) {
            throw new NotLoginError(ResultConstant.MSG_NOT_FOUND_CONTACT);
        }

        User user = usersMapper.selectById(currentId);
        Integer isAdmin = user.getIsAdmin();
        List<ContactPersonVo> contactsAll = getContactsAll();
        if (isAdmin == 1) {
            // 管理员直接根据id查询即可
            for (ContactPersonVo contactPersonVo : contactsAll) {
                if (contactPersonVo.getId().equals(contactId)) {
                    return contactPersonVo;
                }
            }
            throw new NotFoundUserError(ResultConstant.MSG_NOT_FOUND_CONTACT);
        } else if (isAdmin == 0) {
            // 查询出该用户的所用联系人id， 如果该id等于查询出来的id，则返回该联系人信息
            List<Integer> person = contactPersonMapper.getContactPersonByUserId(currentId);
            for (Integer integer : person) {
                // 用户的联系人集合中联系人的id = 要查找的id ， 证明这个这个联系人是这个用户的
                if (Objects.equals(integer, contactId)) {
                    for (ContactPersonVo contactPersonVo : contactsAll) {
                        if (contactPersonVo.getId().equals(contactId)) {
                            return contactPersonVo;
                        }
                    }
                }
            }
        }
        throw new NotFoundUserError(ResultConstant.MSG_NOT_FOUND_USER);
    }

    /**
     * 1. 将 dto 数据拆分出来  联系人 、 联系方式 、 联系组
     * 2. 整理好数据，分别插入到 联系人表、 联系方式表、 联系组表中
     * 3. 返回 联系人vo对象
     *
     * @param contactPersonDto 联系人信息 和 联系对应的组合联系的方式
     * @return
     */
    @Override
    @Transactional // 修改多个表，需要事务
    public ContactPersonVo addContactPerson(ContactPersonDto contactPersonDto) {
        Long currentId = BaseContext.getCurrentId();
        // 联系人的基础信息
        ContactPerson contactPerson = BeanUtil.copyProperties(contactPersonDto, ContactPerson.class);
        contactPerson.setUserId(Math.toIntExact(currentId));
        contactPersonMapper.addContactPerson(contactPerson);

        Integer personId = contactPerson.getId();


        // 联系人对应的联系方式
        List<ContactMethods> methodsList = contactPersonDto.getMethodsList();
        if (methodsList != null && methodsList.size() > 0) {
            for (ContactMethods contactMethods : methodsList) {
                contactMethods.setPersonId(personId);
            }
            // 插入数据
            contactMethodsService.saveBatch(methodsList);
        }

        List<PersonGroupDto> dtos = new ArrayList<>();
        // 联系人对象对应的组 （修改中间表）
        List<ContactGroup> groups = contactPersonDto.getGroups();
        // 构建中间表需要的数据
        if (groups != null && groups.size() > 0) {
            for (ContactGroup group : groups) {
                PersonGroupDto build = PersonGroupDto.builder()
                        .groupId(group.getId())
                        .personId(personId)
                        .createId(Math.toIntExact(currentId))
                        .build();
                dtos.add(build);
            }
        }
        log.info("要插入的数据为：{}", dtos);

        // 向中间表插入数据
        contactPersonMapper.addPersonGroup(dtos);

        // 根据联系人的id查询
        //  新创联系人的基础信息
        ContactPerson byId = getById(personId);
        ContactPersonVo contactPersonVo = BeanUtil.copyProperties(byId, ContactPersonVo.class);
        // 根据联系id查联系方式集合
        List<ContactMethods> contactMethodsList = contactMethodsService.getContactMethodsByPersonId(Collections.singletonList(personId));
        List<ContactMethodsVo> contactMethodsVos = BeanUtil.copyToList(contactMethodsList, ContactMethodsVo.class);
        contactPersonVo.setContactMethods(contactMethodsVos);

        // 根据组id查询组信息
        List<Integer> groupIds = groups.stream().map(ContactGroup::getId).collect(Collectors.toList());
        LambdaUpdateWrapper<ContactGroup> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(ContactGroup::getId, groupIds);
        List<ContactGroup> groupList = contactGroupService.list(wrapper);
        List<ContactGroupVo> groupVos = BeanUtil.copyToList(groupList, ContactGroupVo.class);
        contactPersonVo.setGroups(groupVos);
        return contactPersonVo;
    }


    // TODO : 更新用户数据

    @Override
    @Transactional
    /**
     *   1. 判断这个联系人是否存在
     *   2. 判断当前用户的否是管理员
     *   3. 如果是管理员，直接删除 , 判断该联系人是否是当前用户的联系人
     *   4. 清除中间表中的联系人和组的关系
     */
    public void deleteById(Integer id) {
        Long currentId = BaseContext.getCurrentId();
        // 1.
        ContactPerson byId = getById(id);
        if (byId == null) {
            throw new NotFoundUserError(ResultConstant.MSG_NOT_FOUND_CONTACT);
        }

        // 2.
        User user = usersMapper.selectById(currentId);
        Integer isAdmin = user.getIsAdmin();

        if (isAdmin == 1) {
            // 管理员 直接删除 3 .
            boolean b = removeById(id);
            // 删除失败 未知错误
            if (!b) {
                throw new BaseException(ResultConstant.MSG_UNKNOWN_ERROR);
            }
        } else if (isAdmin == 0) {
            boolean flag = false;
            // 普通用户判断 这个联系人的id 是当前用户的联系人 3.
            List<Integer> person = contactPersonMapper.getContactPersonByUserId(currentId);
            for (Integer integer : person) {
                if (Objects.equals(id, integer)) {
                    flag = true;
                    // 删除失败 未知错误
                    boolean b = removeById(id);
                    if (!b) {
                        throw new BaseException(ResultConstant.MSG_UNKNOWN_ERROR);
                    }
                }
            }
            //  循环结束还是没有修改 flag 的值 ， 说明这个联系人不是当前用的联系人    没有删除
            if (!flag) {
                throw new NotFoundUserError(ResultConstant.MSG_NOT_FOUND_CONTACT);
            }


        }

        // 4. 清除中间表中数据
        contactPersonMapper.closePersonGroupByPersonId(id);
    }
}
